/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package mamayukero.problem.environment;

import java.awt.Point;
import java.io.*;
import java.util.ArrayList;
import java.util.StringTokenizer;
import mamayukero.debug.LogBuilder;
import mamayukero.problem.environment.component.*;
import mamayukero.problem.environment.map.*;

public class Environment {
    public static long	startingMoney,              //starting amount of money
                        currentMoney;               //current amount of money
    public static Map map;                          //where we play
    public static ArrayList<Machine> typesOfMachine;//description for every type of machine available
    public static ArrayList<Product> typesOfProduct;//description for every product
    public static int numberOfMachine,              //kind of machine
                        maxSewaMachine,             //maximum number type of machine (24 hours)
                        hourOfWork;                 //amount hour of work
    
    public static String schedule;
    public static Matrix matrix;
    
    public static void Reset() {
        map = new Map();
        matrix = new Matrix();
        Timer.initTimer();
        startingMoney = 0;
        currentMoney = 0;
        typesOfMachine = new ArrayList<Machine>();
        typesOfProduct = new ArrayList<Product>();
        numberOfMachine = 0;
        maxSewaMachine = 0;
        hourOfWork = 0;
    }
    
    public static void drawMap() {
        for (int i = 0; i < map.row; i++) {
            for (int j = 0; j < map.col; j++) {
                System.out.print(((j == map.factory.getLocation().x) && 
                        (i == map.factory.getLocation().y))? "P " : 
                        (map.block[j][i])? "O " : "X ");
            }
            System.out.println();
        }
    }
    
    public static void initWorkflow(String s) {
        //schedulling
        schedule = s;
        map.truck.pickupSchedule = s;
        map.factory.workSchedule = s;
        
        //production initialization
        Timer.initTimer();
        map.factory.initProduction();
        map.factory.log.clear();
        map.truck.log.clear();
    }
    
    /**
	 * Reading an external file and save it into matrix
	 * @param pFilename 
	 */
        
        public static void load(String pFileName)
	{
            String state = "[START LOADING]";
		try {
			BufferedReader reader = new BufferedReader(new FileReader(pFileName));
                        //$, H, M, N, Y
                        String str = reader.readLine();
                        StringTokenizer mTokenizer = new StringTokenizer(str, " ");
                        state = "[LOAD] START BASE";
                        loadBase(mTokenizer);
                        state = "[LOAD] FINISHED BASE";
                        //Deskripsi Mesin
                        state = "[LOAD] START MACHINE";
                        loadMachine(reader);
                        state = "[LOAD] FINISHED MACHINE";
                        //Deskripsi Vendor
                        state = "[LOAD] START VENDOR AND PRODUCT";
                        loadVendorAndProduct(reader);
                        state = "[LOAD] FINISIHED VENDOR AND PRODUCT";
                        //Deksripsi Map
                        state = "[LOAD] START MAP";
			loadMap(reader);
                        state = "[LOAD] FINISHED MAP";
		} catch (IOException ex) {
			System.out.println(state);
		}
		map.setVendorsStraightLines();
	}
        
        public static void writeReport() {
            try{
                // Create file 
                FileWriter fstream = new FileWriter(Const.FILE_OUTPUT);
                BufferedWriter out = new BufferedWriter(fstream);
                out.write("[WORK REPORT]\n\n");
                out.write("[GENERAL INFORMATION]\n");
                out.write("Starting Money\t: " + startingMoney + "\n\n");
                out.write("[VENDOR INFORMATION]");
                for (Vendor v : Environment.map.vendor) {
                    out.write("\n" + v.toString());
                }
                out.write("\n\n[MACHINOS INFORMATION]");
                for (Machine m : Environment.typesOfMachine) {
                    out.write("\n" + m.toString());
                }
                out.write("\n\n[PRODUCT INFORMATION]");
                for (Product p : Environment.typesOfProduct) {
                    out.write("\n" + p.toString());
                }
                
                out.write("\n\n[FACTORY INFORMATION]");
                out.write("\n" + Environment.map.factory.toString());
                
                out.write("\n\n[FACTORY LOG]");
                for (LogBuilder lc : map.factory.log.getComponent()) {
                    out.write("\n" + lc.toString());
                }
                
                out.write("\n\n[PATHFINDING]");
                out.write("\n[A* LOG]");
                for (LogBuilder lc : map.truck.pathfinding.get(Truck.PF_ASTAR).log.getComponent()) {
                    out.write("\n" + lc.toString());
                }
                
                out.write("\n[BFS LOG]");
                for (LogBuilder lc : map.truck.pathfinding.get(Truck.PF_BFS).log.getComponent()) {
                    out.write("\n" + lc.toString());
                }
                
                out.write("\n[GREEDY LOG]");
                for (LogBuilder lc : map.truck.pathfinding.get(Truck.PF_GREEDY).log.getComponent()) {
                    out.write("\n" + lc.toString());
                }
                
                out.close();
            } catch (Exception e){//Catch exception if any
                System.err.println("Error: " + e.getMessage());
            }
        }
        
        public static void writeReport(File file) {
            try{
                // Create file 
                FileWriter fstream = new FileWriter(file,false);
                BufferedWriter out = new BufferedWriter(fstream);
                out.write("[WORK REPORT]\n\n");
                out.write("[GENERAL INFORMATION]\n");
                out.write("Starting Money\t: " + startingMoney);
                out.write("Rent price\t: " + map.factory.countRent());
                out.write("Assets count\t: " + map.factory.countProfit());
                out.write("\n\n[VENDOR INFORMATION]");
                for (Vendor v : Environment.map.vendor) {
                    out.write("\n" + v.toString());
                }
                out.write("\n\n[MACHINOS INFORMATION]");
                for (Machine m : Environment.typesOfMachine) {
                    out.write("\n" + m.toString());
                }
                out.write("\n\n[PRODUCT INFORMATION]");
                for (Product p : Environment.typesOfProduct) {
                    out.write("\n" + p.toString());
                }
                out.write("\n\n[TRUCK INFORMATION]");
                out.write("\n" + Environment.map.truck.toString());
                //Close the output stream
                
                out.write("\n[TRUCK LOG]");
                for (LogBuilder lc : map.truck.log.getComponent()) {
                    out.write("\n" + lc.toString());
                }
                
                out.write("\n\n[FACTORY INFORMATION]");
                out.write("\n" + Environment.map.factory.toString());
                
                out.write("\n\n[FACTORY LOG]");
                for (LogBuilder lc : map.factory.log.getComponent()) {
                    out.write("\n" + lc.toString());
                }
                
                
                out.write("\n\n[PATHFINDING]");
                out.write("\n[A* LOG]\n");
                for (LogBuilder lc : map.truck.pathfinding.get(Truck.PF_ASTAR).log.getComponent()) {
                    out.write("\n" + lc.toString());
                }
                
                out.write("\n[BFS LOG]\n");
                for (LogBuilder lc : map.truck.pathfinding.get(Truck.PF_BFS).log.getComponent()) {
                    out.write("\n" + lc.toString());
                }
                
                out.write("\n[GREEDY LOG]\n");
                for (LogBuilder lc : map.truck.pathfinding.get(Truck.PF_GREEDY).log.getComponent()) {
                    out.write("\n" + lc.toString());
                }
                
                
                out.close();
            } catch (Exception e){//Catch exception if any
                System.err.println("Error: " + e.getMessage());
            }
        }
        
        private static void loadBase(StringTokenizer mTokenizer) {
            startingMoney = Integer.parseInt(mTokenizer.nextToken());
            hourOfWork = Integer.parseInt(mTokenizer.nextToken());
            numberOfMachine = Integer.parseInt(mTokenizer.nextToken());
            maxSewaMachine = Integer.parseInt(mTokenizer.nextToken());
            map.truck.capacity = Integer.parseInt(mTokenizer.nextToken());
        }
        
        private static void loadMachine(BufferedReader br) throws IOException {
            StringTokenizer mTokenizer;
            String str;
            for (int i = 0; i < numberOfMachine; i++) {
                mTokenizer = new StringTokenizer(br.readLine(), " ");
                typesOfMachine.add(new Machine(i+1,                           //(TIPE) tipe mesin
                                                Integer.parseInt(mTokenizer.nextToken()),     //(T) maksimal jam kerja
                                                Integer.parseInt(mTokenizer.nextToken()),     //(W) maksimal kerja terus menerus
                                                Integer.parseInt(mTokenizer.nextToken()),     //(S) waktu istirahat
                                                Integer.parseInt(mTokenizer.nextToken()),     //(P) jumlah produk yang dihasilkan dalam 1 jam
                                                Integer.parseInt(mTokenizer.nextToken()),     //(I) jumlah produk dependensi yang dibutuhkan
                                                Integer.parseInt(mTokenizer.nextToken()),     //(C) pengurangan jumlah produksi jika terus menerus
                                                Integer.parseInt(mTokenizer.nextToken()),     //(R) biaya sewa dalam 24 jam
                                                Integer.parseInt(mTokenizer.nextToken())));   //(DEPENDENSI) produk dari salah satu
                //DEBUGGING : System.out.println("MESIN KE-" + i + " = " + typesOfMachine.get(i).toString());
            }
        } 
        
        private static void loadVendorAndProduct(BufferedReader br) throws IOException {
            StringTokenizer mTokenizer = new StringTokenizer(br.readLine()," ");
            int numberOfVendor = Integer.parseInt(mTokenizer.nextToken());
            int machinePerVendor = 0;
            for (int i = 0; i < numberOfVendor; i++) {
                mTokenizer = new StringTokenizer(br.readLine(), " ");
                map.vendor.add(new Vendor(i,mTokenizer.nextToken().charAt(0),new Point(0,0)));
                mTokenizer = new StringTokenizer(br.readLine(), " ");
                machinePerVendor = Integer.parseInt(mTokenizer.nextToken());
                for (int j = 0; j < machinePerVendor; j++) {
                    map.vendor.get(i).addMachine(new Machine(typesOfMachine.get(Integer.parseInt(mTokenizer.nextToken())-1)));
                }
                //DEBUGGING : System.out.println("VENDOR KE-" + i + " = " + map.vendor.get(i).toString());
            }
            for (int i = 0; i < numberOfMachine; i++) {
                mTokenizer = new StringTokenizer(br.readLine(), " ");
                typesOfProduct.add(new Product(Integer.toString(i+1),Integer.parseInt(mTokenizer.nextToken())));
                //DEBUGGING : System.out.println("PRODUCT KE-" + i + " = " + typesOfProduct.get(i).toString());
            }
            
        }
        
        private static void loadMap(BufferedReader br) throws IOException {
            ArrayList<Character> tRow;
            char c;
            String str;
            StringTokenizer mTokenizer = new StringTokenizer(br.readLine());
            int iRow = Integer.parseInt(mTokenizer.nextToken()),iCol = Integer.parseInt(mTokenizer.nextToken());
            for (int i = 0; i < iRow; i++) {
                str = br.readLine();
                tRow = new ArrayList<Character>();
                for (int j = 0; j < iCol; j++) {
                    c = str.charAt(j);
                    tRow.add(c);
                     if (c == Const.FACTORY) {
                            map.factory.setLocation(new Point(j,i));
                    } else if ((c != Const.MOVEABLE) && (c != Const.UNMOVEABLE)) {
                            Vendor.findVendorwName(map.vendor, c).setLocation(new Point(j,i));
                    }
                }
                matrix.setRow(tRow);
                tRow.clear();
            }
            map.initBlock(iRow, iCol, matrix);
            map.truck.initMap();
        }
        
        //CONTROLLING environment
        public static boolean timesUp() {
            return Timer.getHour() >= hourOfWork; 
        }
        
        public static void turn() {
            map.truck.move();
            map.factory.incCounter();
            Timer.incMinute();
        }
        
        
}
